/*
 * @Author: xitontong
 * @Date: 2020-03-09 11:43:19
 * @LastEditTime: 2020-05-08 09:52:34
 * @LastEditors: xitontong
 * @Description: 
 */
#include "FishGameMain.h"
#include "NFComm/NFMessageDefine/NFMsgDefine.h"

bool FishGameMain::Init(){

    // string content;
    // std::string strFile = pPluginManager->GetConfigPath() + "NFDataCfg/groups.json";
    // pPluginManager->GetFileContent(strFile,content);
    // ajson::load_from_buff(m_allFishGroups,content.c_str());
    return true;
}


bool FishGameMain::AfterInit(){
    m_pSceneModule = pPluginManager->FindModule<NFISceneModule>();
    m_pElementModule = pPluginManager->FindModule<NFIElementModule>();
    m_pKernelModule = pPluginManager->FindModule<NFIKernelModule>();
    m_pScheduleModule = pPluginManager->FindModule<NFIScheduleModule>();
    m_pClassModule = pPluginManager->FindModule<NFIClassModule>();
    m_pSceneModule->AddBeforeEnterSceneGroupCallBack(this,&FishGameMain::BeforeEnterSceneGroup);
    m_pSceneModule->AddAfterLeaveSceneGroupCallBack(this,&FishGameMain::AfterLeaveSceneGroup);
    m_pSceneModule->AddAfterEnterAndReadySceneGroupCallBack(this,&FishGameMain::AfterEnterAndSceneRead);
    m_pGameServerNet_ServerModule = pPluginManager->FindModule<NFIGameServerNet_ServerModule>();
    m_pNetModule = pPluginManager->FindModule<NFINetModule>();
    m_pPropertyModule = pPluginManager->FindModule<NFIPropertyModule>();


    m_pKernelModule->AddClassCallBack(NFrame::Fish::ThisName(), this, &FishGameMain::OnObjectClassEvent);


    m_pNetModule->AddReceiveCallBack(NFMsg::REQ_USE_SKILL,this,&FishGameMain::OnReqUseSkill);
    m_pNetModule->AddReceiveCallBack(NFMsg::REQ_CATCH_CHECK,this,&FishGameMain::OnReqCatchCheck);
    m_pLogModule = pPluginManager->FindModule<NFILogModule>();
    return true;
}
int FishGameMain::BeforeEnterSceneGroup(const NFGUID & self, const int nSceneID, const int nGroupID, const int nType, const NFDataList & argList){
    
    //分配seatId
    SetValidSeatId(nSceneID,nGroupID,self);
    string sSceneId = std::to_string(nSceneID);
    NFMsg::EGameType eGameType = (NFMsg::EGameType)m_pElementModule->GetPropertyInt32(sSceneId, NFrame::Scene::MainGameType());
    if(eGameType != NFMsg::EGameType::FISH){
        return 0;
    }
    int count = m_pKernelModule->GetGroupObjectList(nSceneID,nGroupID,true,self);
    if(count<=0){
        StartTableClock(nSceneID,nGroupID);
    }
    return 0;
}
void FishGameMain::OnReqCatchCheck(const NFSOCK sockIndex, const int msgID, const char* msg, const uint32_t len){
	CLIENT_MSG_PROCESS( msgID, msg, len, NFMsg::MsgFishCatchCheck);
    const int sceneID = m_pKernelModule->GetPropertyInt(nPlayerID, NFrame::Player::SceneID());
    const int groupID = m_pKernelModule->GetPropertyInt(nPlayerID, NFrame::Player::GroupID());

    NFGUID fishId = NFINetModule::PBToNF(xMsg.fish_id());
    //计算概率
    cout<<"<<<"<<fishId.ToString()<<endl;
    default_random_engine e(static_cast<unsigned int>(time(nullptr)));
    uniform_int_distribution<unsigned> u(0,100);
    int randomInt = u(e);
    auto fishObj= m_pKernelModule->GetObject(fishId);
    int catchProbability = fishObj->GetPropertyInt(NFrame::Fish::killProbability());
    //TODO 概率计算
    bool isCatched = catchProbability>randomInt;
    if(isCatched){
        fishObj->SetPropertyObject(NFrame::Fish::killer(),nPlayerID);
        // m_pGameServerNet_ServerModule->SendGroupMsgPBToGate(NFMsg::ACK_CATCH_CHECK, xMsg, sceneID, groupID);
    }
}
int FishGameMain::OnObjectClassEvent( const NFGUID& self, const std::string& className, const CLASS_OBJECT_EVENT classEvent, const NFDataList& var ){
    if (className != NFrame::Fish::ThisName()){
        return 0;
    }
    NF_SHARE_PTR<NFIObject> pSelf = m_pKernelModule->GetObject(self);
    if (nullptr == pSelf)
    {
        return 1;
    }
    if (CLASS_OBJECT_EVENT::COE_CREATE_HASDATA != classEvent )
    {

    }
    m_pKernelModule->AddPropertyCallBack(self, NFrame::Fish::killer(), this, &FishGameMain::OnObjectKillerEvent);
}
int FishGameMain::OnObjectKillerEvent( const NFGUID& self, const std::string& propertyName, const NFData& oldVar, const NFData& newVar)
{
    const NFGUID& identAttacker = newVar.GetObject();
    if (identAttacker.IsNull())
    {
        return 0;
    }
    //只能有一个击杀者
    if(!oldVar.GetObject().IsNull()){
        return 0;
    }
    if (identAttacker.IsNull())
    {
        return 0;
    }
    const int64_t gold = m_pKernelModule->GetPropertyInt(self, NFrame::Fish::HP());
    m_pPropertyModule->AddGold(identAttacker, gold);
    return 0;
}
void FishGameMain::OnReqUseSkill(const NFSOCK sockIndex, const int msgID, const char* msg, const uint32_t len){
	CLIENT_MSG_PROCESS( msgID, msg, len, NFMsg::ReqUseSkill);
    const int sceneID = m_pKernelModule->GetPropertyInt(nPlayerID, NFrame::Player::SceneID());
    const int groupID = m_pKernelModule->GetPropertyInt(nPlayerID, NFrame::Player::GroupID());
    //检查金币持有数量
    int goldCount = m_pKernelModule->GetPropertyInt(nPlayerID,NFrame::Player::Gold());
    m_pKernelModule->SetPropertyInt(nPlayerID,NFrame::Player::Gold(),goldCount-100);
    m_pGameServerNet_ServerModule->SendGroupMsgPBToGate(NFMsg::ACK_USE_SKILL, xMsg, sceneID, groupID);
}
int FishGameMain::AfterEnterAndSceneRead(const NFGUID & self, const int nSceneID, const int nGroupID, const int nType, const NFDataList & argList){
    NF_SHARE_PTR<NFIGameServerNet_ServerModule::GateBaseInfo> pDataBase = m_pGameServerNet_ServerModule->GetPlayerGateInfo(self);
    if (!pDataBase)
    {
        return 0;
    }
    auto startTime = lexical_cast<long>(m_pSceneModule->GetPropertyString(nSceneID,nGroupID,NFrame::Group::StartTime()));
    auto elapseTime = NFGetTimeMS()-startTime;
    NFMsg::AckFishEnterRoomFinish xMsg;
    xMsg.set_group_id(nGroupID);
    cout<<"------>>>同步当前时间---->"<<elapseTime<<endl;
    xMsg.set_table_time_elapse(elapseTime/1000.0);
    NFDataList roomUsers;
    NFDataList xList;
    m_pKernelModule->GetGroupObjectList(nSceneID, nGroupID, xList, true,self);
    
    // *xMsg.mutable_event_client() = NFINetModule::NFToPB(pDataBase->xClientID);
    // *xMsg.mutable_event_object() = NFINetModule::NFToPB(self);
    m_pGameServerNet_ServerModule->SendMsgPBToGate(NFMsg::ACK_SYNC_GAME_INFO, xMsg, self);
    //查找可用的seatId
    //tableTime
    //发送开始消息
    return 0;
}
void FishGameMain::SetValidSeatId(const int nSceneID, const int nGroupID,const NFGUID & self){
    auto name = GetSceneGroupScheduleName(nSceneID,nGroupID);
    int seatId = 0;
    const int nMaxPlayer = m_pElementModule->GetPropertyInt32(std::to_string(nSceneID), NFrame::Scene::MaxGroupPlayers());
    NFDataList xList;
    m_pKernelModule->GetGroupObjectList(nSceneID, nGroupID, xList, true,self);
    for(int i=1;i<=nMaxPlayer;i++){
       NF_SHARE_PTR<NFData> data =  xList.GetStack(i-1);
       int otherSeatId = m_pKernelModule->GetPropertyInt(data->GetObject(),NFrame::Player::SeatId());
        cout<<"可行的seatId----xxx->>"<<otherSeatId<<"  "<<data->GetObject().ToString()<<endl;
       if(otherSeatId == i){
           continue;
       }
       seatId = i;
       break;
    }
    cout<<"可行的seatId----->>"<<seatId<<endl;
    m_pKernelModule->GetObject(self)->SetPropertyInt(NFrame::Player::SeatId(),seatId);
}
int FishGameMain::AfterLeaveSceneGroup(const NFGUID & self, const int nSceneID, const int nGroupID, const int nType, const NFDataList & argList){
       string sSceneId = std::to_string(nSceneID);
    NFMsg::EGameType eGameType = (NFMsg::EGameType)m_pElementModule->GetPropertyInt32(sSceneId, NFrame::Scene::MainGameType());
    if(eGameType != NFMsg::EGameType::FISH){
        return 0;
    }
    NFDataList dataList;
    int count = m_pKernelModule->GetGroupObjectList(nSceneID,nGroupID,true,self);
    std::cout<<"离开---->>"<<nSceneID<<"==="<<nGroupID<<"   :"<<count<<endl;
    NFDataList varObjectList;
    if (m_pKernelModule->GetGroupObjectList(nSceneID, nGroupID, varObjectList, true) && varObjectList.GetCount() <= 0)
    // if(count<=0)
    {
        //桌子定时器
        auto name = GetSceneGroupScheduleName(nSceneID,nGroupID);
        std::cout<<"取消定时器:"<<nGroupID<<"   "<<name<<endl;
        m_pScheduleModule->RemoveSchedule(name);
    }
    return 0;
}
void FishGameMain::AddNetMsgListener(){
    
}
//process group data,create group elements
void FishGameMain::processGroups(int nSceneId,int nGroupId,NF_SHARE_PTR<NFIRecord> fishGroups){
    auto startTime = lexical_cast<long>(m_pSceneModule->GetPropertyString(nSceneId,nGroupId,NFrame::Group::StartTime()));
    auto elapseTime = NFGetTimeMS()-startTime;


    for(int i = 0;i<fishGroups->GetUsedRows();i++){
        string pathId = fishGroups->GetString(i,NFrame::FishGroup::fish_group_1::PathId);
        int enterTime = fishGroups->GetFloat(i,NFrame::FishGroup::fish_group_1::EnterTime);
        int aliveTime = fishGroups->GetFloat(i,NFrame::FishGroup::fish_group_1::ExitTime);
        string fishResId = fishGroups->GetString(i,NFrame::FishGroup::fish_group_1::ResId);

        NFDataList dataList;
        dataList.AddString(NFrame::Fish::pathId());
        dataList.AddString(pathId);

        float realEnterTime = enterTime+elapseTime/1000.0;
        dataList.AddString(NFrame::Fish::enterTime());
        dataList.AddFloat(realEnterTime);

        auto fishId = m_pKernelModule->CreateGUID();
        cout<<"创建鱼:"<<fishId.ToString()<<endl;
        m_pKernelModule->CreateObject(fishId,nSceneId,nGroupId,NFrame::Fish::ThisName(),fishResId,dataList);
    }
}
//添加鱼群
void FishGameMain::groupLogic(int nSceneId,int nGroupId){
    auto groupName = GetSceneGroupScheduleName(nSceneId,nGroupId);
    auto groupManager = m_pClassModule->GetClassRecordManager(NFrame::FishGroup::ThisName());
	auto allFishGroups = groupManager->GetElement(NFrame::FishGroup::AllFishGroup::ThisName());
    int usedCount = allFishGroups->GetUsedRows();
    default_random_engine e(static_cast<unsigned int>(time(nullptr)));
    uniform_int_distribution<unsigned> u(0,usedCount-1);
    int groupRow = u(e);

    //选择GroupID
    string groupId = allFishGroups->GetString(groupRow,NFrame::FishGroup::AllFishGroup::GroupId);
    
    auto fishGroup = groupManager->GetElement(groupId);
    usedCount = fishGroup->GetUsedRows();
    float maxEnterTime = 0;
    for(int i=0;i<usedCount;i++){
        float enterTime = fishGroup->GetFloat(i,NFrame::FishGroup::fish_group_1::EnterTime);
        if(enterTime>maxEnterTime){
            maxEnterTime = enterTime;
        }
    }
    processGroups(nSceneId,nGroupId,fishGroup);
    //获取最大进入时间
    m_pScheduleModule->AddSchedule(NFGUID(),groupName,this,&FishGameMain::SceneGroupScheduler,maxEnterTime,1);
}


void FishGameMain::StartTableClock(int nSceneId,int nGroupId){
    //set start time
    m_pSceneModule->SetPropertyString(nSceneId,nGroupId,NFrame::Group::StartTime(),lexical_cast<string>(NFGetTimeMS()));
    //schedule name
    auto groupName = GetSceneGroupScheduleName(nSceneId,nGroupId);
    //first time ,add fish group immediately
    m_pScheduleModule->AddSchedule(NFGUID(),groupName,this,&FishGameMain::SceneGroupScheduler,0,1);
}
void FishGameMain::StopTableClock(int nSceneId,int nGroupId){
    
}
std::string FishGameMain::GetSceneGroupScheduleName(const int nSceneID, const int nGroupID){

    return string("schedule|")+to_string(nSceneID)+"|"+to_string(nGroupID);
}
//room loop logic
int FishGameMain::SceneGroupScheduler(const NFGUID&,const std::string& name, const float interval, const int count){
    NFDataList dataList;
    dataList.Split(name,"|");
    int sceneId = lexical_cast<int>(dataList.String(1));
    int groupId = lexical_cast<int>(dataList.String(2));
    int online = m_pKernelModule->GetGroupObjectList(sceneId,groupId,dataList,true);
    NFDataList arg;
    groupLogic(sceneId,groupId);
}